#ifndef BRANCH_H
#define BRANCH_H

#include "reshoughtools.h"

class Branch
{
public:
    /**
     * @brief Branch
     * Constructeur par defaut
     * Tout est initialise a 0 ou NULL
     */
    Branch();

    /**
     * @brief Branch
     *
     * Constructeur avec initialisation des attributs importants
     *
     * @param head : Pointeur vers le premier cercle de la branche
     * @param tail : Pointeur vers le dernier cercle de la branche
     */
    Branch(nodePtr _head, nodePtr _tail, nodePtr _father, vcg::Point3f _bot, vcg::Point3f _top );

    /**
     * @brief Branch
     *
     * Constructeur par copie
     * \warning Le pointeur vers le mesh n'est pas copie. A la place on met NULL
     *
     * @param branch : Branche a copier
     */
    Branch( const Branch& _branch );

    /**
     * @brief ~Branch
     *
     * Destructeur
     *
     */
    ~Branch();

    void drawBranch (MeshDocument& m , bool drawCircles, bool drawSkeleton, bool drawBBox, QString title = "Branch" );

    /*!
     * \brief colorizeMesh
     *
     * Colorize la branche (le maillage de la branche) dans la couleur donnee en parametre
     *
     * \param _color : Couleur dans laquelle afficher la branche
     */
    void colorizeMesh ( vcg::Color4b _color );

    /*!
     * \brief createBranchMesh
     *
     * Ajoute au maillage de la branche les cylindres la composant
     */
    void createBranchMesh ();

    /*!
     * \brief createBranchSkeleton
     *
     * Ajoute au maillage de la branche les points du squelette la composant
     */
    void createBranchSkeleton ();

    /*!
     * \brief createBranchBBox
     *
     * Ajoute au maillage de la branche sa bounding box
     */
    void createBranchBBox ();

    /*!
     * \brief setHead
     *
     * Setter de la classe
     *
     * \param _head : Nouvelle tete de la branche
     */
    inline void setHead( nodePtr _head ) { head = _head; }

    /*!
     * \brief setTail
     *
     * Setter de la classe
     *
     * \param _tail : Nouvelle queue de la branche
     */
    inline void setTail ( nodePtr _tail ) { tail = _tail; }

    inline vcg::Point3f getTop () { return top; }
    inline vcg::Point3f getBot () { return bot; }
    inline nodePtr  getHead () { return head; }
    inline nodePtr  getTail () { return tail; }
    inline nodePtr  getFather () { return father; }

    /*!
     * \brief updateBBox
     *
     * Met a jour la bounding box de la branche lorsqu'un nouveau point y est insere
     *
     * \param p : Point a inserer dans la branche
     */
    inline void updateBBox ( vcg::Point3f p )
    {
        if ( p[0] < bot[0] )
            bot[0] = p[0];

        if ( p[1] < bot[1] )
            bot[1] = p[1];

        if ( p[2] < bot[2] )
            bot[2] = p[2];

        if ( p[0] > top[0] )
            top[0] = p[0];

        if ( p[1] > top[1] )
            top[1] = p[1];

        if ( p[2] > top[2] )
            top[2] = p[2];
    }

    /*!
     * \brief distance
     *
     * Renvoie la distance avec la branche passee en parametre. Cette distance est calculee en fonction de la bounding box
     *
     * \param branch : Branche dont on veut connaitre la distance
     *
     * \return La distance entre l'objet et la branche passe en parametre
     */
    float distance ( Branch* branch );

    /*!
     * \brief size
     *
     * Renvoie la taille de la branche (le nombre de noeuds qu'elle contient)
     *
     * \return Nombre de noeuds dans la branche
     */
    inline unsigned int size()
    {
        if ( head == tail )
        {
            // Il n'y a que la tete
            return 1;
        }

        unsigned int size = 0;
        for ( nodePtr currentNode = head ; currentNode != tail->up ; currentNode = currentNode->up )
        {
            size++;
        }

        return size;
    }

private :
    /* Attributs */
    nodePtr head;               /*!< Pointeur vers le premier cercle de la branche */
    nodePtr tail;               /*!< Pointeur vers le dernier cercle de la branche */
    nodePtr father;             /*!< Pointeur vers le noeud de bifurcation */
    vcg::Point3f bot;           /*!< Coin bas-gauche de la bounding box des cercles formant l'arbre */
    vcg::Point3f top;           /*!< Coin haut-droit de la bounding box des cercles formant l'arbre */
    MeshModel*   branchMesh;    /*!< Pointeur vers le mesh engendre par l'arbre */
    QString      layerTitle;    /*!< Nom du layer qui va contenir le maillage */
};

#endif // BRANCH_H
